//@version=5
// -----------------------------------------------------------------------------
// | © AlgoPoint                                                               |
// | Indicator: Climax Absorption Engine [AlgoPoint]                           |
// | Developer: Harmony Algo & AlgoPoint Collaboration                         |
// -----------------------------------------------------------------------------

indicator("Climax Absorption Engine [AlgoPoint]", "Climax Absorption Engine [AlgoPoint]", overlay=true, max_labels_count = 500)

// =============================================================================
//                                  SETTINGS
// =============================================================================
signalvisualmode = input.string(title='Signal Visual', defval = 'Classic', options = ['Classic', 'Minimal'], group = 'Signal Settings')

momentum_group = "1. Momentum Detection"
momentum_len = input.int(3, "Consecutive Bars", group=momentum_group, tooltip="Minimum number of consecutive same-color bars to define a momentum move.")
ema_len = input.int(20, "Momentum EMA", group=momentum_group)
slope_threshold = input.float(0.05, "EMA Slope Threshold (%)", group=momentum_group, tooltip="The minimum slope of the EMA to be considered a strong momentum move.")

climax_group = "2. Climax Detection"
vol_lookback = input.int(50, "Volume Lookback", group=climax_group)
vol_multiplier = input.float(2.5, "Volume Multiplier", group=climax_group, tooltip="A volume spike is detected if the current volume is this many times greater than its average.")

confirmation_group = "3. Confirmation & Signal"
confirmation_window = input.int(3, "Confirmation Window (Bars)", group=confirmation_group, tooltip="How many bars to wait for a reversal candle after a climax event.")

// =============================================================================
//                                  CALCULATIONS
// =============================================================================

// --- Step 1: High-Momentum Move Detection ---
f_isMomentum(bars) =>
    bool is_up = true
    bool is_down = true
    for i = 0 to bars - 1
        is_up := is_up and close[i] > open[i]
        is_down := is_down and close[i] < open[i]
    [is_up, is_down]

[is_up_move, is_down_move] = f_isMomentum(momentum_len)

ema_val = ta.ema(close, ema_len)
ema_slope = (ema_val / ema_val[1] - 1) * 100
is_steep_slope = math.abs(ema_slope) > slope_threshold

in_bull_momentum = is_up_move and is_steep_slope and ema_slope > 0
in_bear_momentum = is_down_move and is_steep_slope and ema_slope < 0

// --- Step 2: Climax Volume Candle Identification ---
avg_vol = ta.sma(volume, vol_lookback)
is_climax_volume = volume > avg_vol * vol_multiplier
is_bull_climax = is_climax_volume and in_bull_momentum
is_bear_climax = is_climax_volume and in_bear_momentum

// =============================================================================
//                      STATE MANAGEMENT & SIGNAL LOGIC
// =============================================================================

// Variables to store the state of a detected climax
var bool climax_setup_active = false
var float climax_midpoint = na
var int climax_direction = 0 // 1 for Bullish climax, -1 for Bearish climax
var int bars_since_climax = 0

// A new climax event sets up the potential for a reversal signal
if is_bull_climax[1] or is_bear_climax[1]
    climax_setup_active := true
    climax_midpoint := (high[1] + low[1]) / 2
    climax_direction := is_bull_climax[1] ? 1 : -1
    bars_since_climax := 0

// --- Step 3: Confirmation & Reversal Signal ---
bool buy_signal = false
bool sell_signal = false

if climax_setup_active
    bars_since_climax += 1
    
    // Check for a Bullish Reversal (after a bearish climax/dump)
    if climax_direction == -1 and close > open and close > climax_midpoint
        buy_signal := true
        climax_setup_active := false // Reset after signal

    // Check for a Bearish Reversal (after a bullish climax/pump)
    if climax_direction == 1 and close < open and close < climax_midpoint
        sell_signal := true
        climax_setup_active := false // Reset after signal

    // Timeout: If no confirmation within the window, cancel the setup
    if bars_since_climax >= confirmation_window
        climax_setup_active := false

// =============================================================================
//                               VISUALIZATION & ALERTS
// =============================================================================
// Plot a shape on the climax candle to mark it
plotshape(is_bull_climax or is_bear_climax, "Climax Candle", shape.diamond, location.top, color.new(color.yellow, 0), size=size.small, offset=-1)

// Plot the final BUY/SELL signals
rsi = ta.rsi(close,21)
buy_signal_text_minimal = rsi < 25 ? 'Strong' : rsi < 35 ? 'Buy' : '▲'
buy_signal_text_normal = 'Capitulation Selling is Over\n(Buyers Are Now in Control)'
buy_signal_text = signalvisualmode == 'Classic' ? buy_signal_text_normal : buy_signal_text_minimal
buy_signal_size = signalvisualmode == 'Classic' ? size.normal : rsi < 25 ? size.normal : rsi < 35 ? size.normal : size.small

sell_signal_text_minimal = rsi > 75 ? 'Strong' : rsi > 65 ? 'Sell' : '▼'
sell_signal_text_normal = 'FOMO Buying is Over\n(Sellers Are Now in Control)'
sell_signal_text = signalvisualmode == 'Classic' ? sell_signal_text_normal : sell_signal_text_minimal
sell_signal_size = signalvisualmode == 'Classic' ? size.normal : rsi > 75 ? size.normal : rsi > 65 ? size.normal : size.small

y1 = low - (ta.atr(30) * 1.25)
y2 = high + (ta.atr(30) * 1.25)

if buy_signal
    label.new(bar_index , y1, buy_signal_text, color=#018208, style=label.style_label_up, textcolor=color.white, size=buy_signal_size)

if sell_signal
    label.new(bar_index , y2, sell_signal_text, color=#d12208, style=label.style_label_down, textcolor=color.white, size=sell_signal_size)

// if is_bull_climax
//     label.new(bar_index , low, text = '⭐️',color=color.new(color.yellow, 100), style=label.style_label_down, textcolor=color.new(color.yellow, 0), size=size.normal)

// if is_bear_climax
//     label.new(bar_index , high, text = '⭐️',color=color.new(color.yellow, 100), style=label.style_label_down, textcolor=color.new(color.yellow, 0), size=size.normal)

// --- Alerts ---
alertcondition(is_bull_climax[1] or is_bear_climax[1], "Climax Candle Detected", "A climax volume candle has been detected. Watch for a potential reversal.")
alertcondition(buy_signal, "Climax Reversal BUY", "Climax Absorption Engine: BUY Signal Confirmed")
alertcondition(sell_signal, "Climax Reversal SELL", "Climax Absorption Engine: SELL Signal Confirmed")